﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Xml;
using System.Xml.Serialization;
using System.IO;
using System.Windows.Forms;
using System.Diagnostics;

namespace PenLiveUpdate {
    public class AutoUpdater {
        const string LOCALFILENAME = "AutoUpdater.xml";
        const string SERVERFILENAME = "AutoUpdater.xml";
        private string serverURL = null;
        private string theFolderPath;
        private string theCurrentRunPath;
        private bool bNeedRestart = false;

        Dictionary<string, FileInfo> listRemotFile;
        Dictionary<string, FileInfo> listLocalFile;

        List<DownloadFileInfo> downloadList = new List<DownloadFileInfo>( ); //需下载的文件列表

        List<FileInfo> preDeleteFile = new List<FileInfo>( ); //需删除的文件列表

        public string TheFolderPath {
            get { return theFolderPath; }
            set { theFolderPath = value; }
        }

        public List<DownloadFileInfo> DownloadList {
            get { return downloadList; }
            set { downloadList = value; }
        }

        public List<FileInfo> PreDeleteFile {
            get { return preDeleteFile; }
            set { preDeleteFile = value; }
        }

        public AutoUpdater () {
            theCurrentRunPath = AppDomain.CurrentDomain.BaseDirectory; //得到当前运行路径
            theFolderPath = System.IO.Path.GetTempPath( ); ; //得到系统的临时文件夹
            serverURL = GetServerUrl();  //得到服务器地址
            DownloadFile( SERVERFILENAME); // 下载服务器配置文件
            listRemotFile = GetFileList(theFolderPath + SERVERFILENAME);
            listLocalFile = GetFileList(theCurrentRunPath + LOCALFILENAME);
        }

        //下载单个文件
        const int C_ReadLen = 64 * 1024;
        const int C_SyncReadTimeout = 1000;

        private bool DownloadFile ( string fileName ) {
            FileStream aFileStream = null;
            try {
                HttpWebRequest aRequest = WebRequest.Create(serverURL+fileName) as HttpWebRequest;
                aRequest.Credentials = CredentialCache.DefaultCredentials;
                WebResponse wsp = aRequest.GetResponse( );
                Stream aStream = wsp.GetResponseStream( );
                aStream.ReadTimeout = C_SyncReadTimeout;
                byte[ ] buffer = new byte[C_ReadLen];
                int offset = 0;
                int readCnt = 0;
                string downloadedName = fileName;//这一行需要修改，要自己起文件名字
                //   Directory.CreateDirectory(Path.GetDirectoryName(downloadedName));
                aFileStream = new FileStream(theFolderPath+ @"\" + fileName, FileMode.Create);//这一行需要修改，要自己起文件名字
                do {
                    readCnt = aStream.Read(buffer, 0, C_ReadLen);
                    aFileStream.Write(buffer, 0, readCnt);
                    offset += readCnt;
                } while (readCnt > 0);
                aFileStream.Close( );
            }
            catch (Exception ex) {
                if (aFileStream != null) {
                    aFileStream.Close( );
                }
                throw ex;
                return false;
            }
            return true;
        }

        public bool NeedUpdate() {

            string thePreUpdateDate = GetTheLastUpdateTime(theCurrentRunPath+LOCALFILENAME);
            string theLastsUpdateDate = GetTheLastUpdateTime(theFolderPath+SERVERFILENAME);
            if (thePreUpdateDate != "") {
                //如果客户端将升级的应用程序的更新日期大于服务器端升级的应用程序的更新日期 
                if (Convert.ToDateTime(thePreUpdateDate) >= Convert.ToDateTime(theLastsUpdateDate)) {
                    return false; //无需下载，当前是最新
                }
            }

            //得到下载列表和本地文件删除列表
             foreach (FileInfo file in listLocalFile.Values)
            {
                if (listRemotFile.ContainsKey(file.Path))
                {
                    FileInfo rf = listRemotFile[file.Path];
                    if (rf.LastVer != file.LastVer)
                    {
                        downloadList.Add(new DownloadFileInfo(rf.Url, file.Path, rf.LastVer, rf.Size));

                    }

                    listRemotFile.Remove(file.Path);
                }
                else
                {
                    preDeleteFile.Add(file);
                }
            }

            foreach (FileInfo file in listRemotFile.Values)
            {
                downloadList.Add(new DownloadFileInfo(file.Url, file.Path, file.LastVer, file.Size));
            }


            return true;
        }


        private string GetServerUrl () {
            string URL = "";
            string AutoUpdaterFileName = theCurrentRunPath+LOCALFILENAME;
            if (!File.Exists(AutoUpdaterFileName))
                return URL;
            //打开xml文档
            FileStream myFile = new FileStream(AutoUpdaterFileName, FileMode.Open);
            // xml文件阅读器
            XmlTextReader xml = new XmlTextReader(myFile);
            while (xml.Read( )) {
                if (xml.Name == "ServerUrl") {
                    // 获取服务器地址 
                    URL = xml.GetAttribute("URL");
                    break;
                }
            }
            xml.Close( );
            myFile.Close( );
            return URL;
        }

        private string GetTheLastUpdateTime ( string fileName ) {
            string LastUpdateTime = "";
            string AutoUpdaterFileName = fileName;
            if (!File.Exists(AutoUpdaterFileName))
                return LastUpdateTime;
            //打开xml文档
            FileStream myFile = new FileStream(AutoUpdaterFileName, FileMode.Open);
            // xml文件阅读器
            XmlTextReader xml = new XmlTextReader(myFile);
            while (xml.Read( )) {
                if (xml.Name == "UpdateTime") {
                    // 获取升级文档的最后一次更新日期 
                    LastUpdateTime = xml.GetAttribute("Date");
                    break;
                }
            }
            xml.Close( );
            myFile.Close( );
            return LastUpdateTime;
        }

        public void StartDownload ( AutoUpdater au, List<DownloadFileInfo> downloadList ) {
            DownloadProgress dp = new DownloadProgress(au, downloadList);
            FrmComplateDownload cd = new FrmComplateDownload(au, downloadList, preDeleteFile);
            if (dp.ShowDialog( ) == DialogResult.OK) {
                //更新成功

                cd.ShowDialog( );

            }
        }

        private Dictionary<string, FileInfo> GetFileList ( string filePathName ) {

            Dictionary<string, FileInfo> list = new Dictionary<string, FileInfo>( );

            string AutoUpdaterFilePathName = filePathName;
            if (!File.Exists(AutoUpdaterFilePathName))
                return list;
            //打开xml文档
            FileStream myFile = new FileStream(AutoUpdaterFilePathName, FileMode.Open);
            // xml文件阅读器
            XmlTextReader xml = new XmlTextReader(myFile);
            while (xml.Read( )) {
                if (xml.Name == "file") {
                    //添加文件列表 
                    list.Add(xml.GetAttribute("path"), new FileInfo(xml.GetAttribute("path"), xml.GetAttribute("url"), xml.GetAttribute("lastver"), Convert.ToInt32(xml.GetAttribute("size"))));
                }
            }
            xml.Close( );
            myFile.Close( );
          

            return list;
        }
    }



    public class FileInfo {
        private string path = "";
        private string url = "";
        private string lastver = "";
        private int size = 0;


        public string Path { get { return path; } }
        public string Url { get { return url; } }
        public string LastVer { get { return lastver; } }
        public int Size { get { return size; } }


        public FileInfo ( string path, string url, string lastVer, int size ) {
            this.path = path;
            this.url = url;
            this.lastver = lastVer;
            this.size = size;
        }
    }


    public class DownloadFileInfo {
        string downloadUrl = "";
        string fileName = "";
        string lastver = "";
        int size = 0;

        /// <summary>
        /// 要从哪里下载文件
        /// </summary>
        public string DownloadUrl { get { return downloadUrl; } }
        /// <summary>
        /// 下载完成后要放到哪里去
        /// </summary>
        public string FileFullName { get { return fileName; } }
        public string FileName { get { return Path.GetFileName(FileFullName); } }
        public string LastVer { get { return lastver; } set { lastver = value; } }
        public int Size { get { return size; } }

        public DownloadFileInfo ( string url, string name, string ver, int size ) {
            this.downloadUrl = url;
            this.fileName = name;
            this.lastver = ver;
            this.size = size;
        }
    }
}
